
import fs from "fs";
import { IResult, Result } from "../tsgf/Result";
import { IDbHelper } from "./DbHelper";

const allConfigs: Map<string, any> = new Map<string, any>();

export interface BaseServerCfg {
    port: number;
}
export interface ConnString {
    appDb: DbConnString;
}
export interface DbConnString {
    mysql: string
}

/**
 * 开始监控配置文件,并返回读取到的配置对象
 * @param configPath 配置文件路径
 * @param configChanged 当配置文件有变化时触发，需要调用getConfig获取最新的配置
 * @returns 
 */
export function startWatchConfig(configPath: string, configChanged: (() => void) | null = null): IResult<any> {
    if (allConfigs.get(configPath) === undefined) {
        //如果是首次启动,则开始监听
        if (!fs.existsSync(configPath)) return Result.buildErr<any>("配置文件[" + configPath + "]不存在!");
        fs.watchFile(configPath, { persistent: false, interval: 500 }, () => {
            allConfigs.set(configPath, null);
            configChanged?.call(null);
        });
        allConfigs.set(configPath, null);
    }

    return getConfig(configPath);
}
/**
 * 读取配置文件,如果配置没变更将从缓存中读取,需要调用过startWatchConfig初始化!
 * @param configPath 配置文件路径
 * @returns 
 */
export function getConfig(configPath: string): IResult<any> {
    let config = allConfigs.get(configPath);
    if (!config) {
        let configFileText: string;
        try {
            let fileBin = fs.readFileSync(configPath);
            if (!fileBin) {
                return Result.buildErr("配置文件[" + configPath + "]读取为空!可能是没权限!");
            }
            if (fileBin[0] === 0xEF && fileBin[1] === 0xBB && fileBin[2] === 0xBF) {
                fileBin = fileBin.slice(3);
            }
            configFileText = fileBin.toString('utf-8');
        } catch (ex) {
            return Result.buildErr("配置文件[" + configPath + "]读取失败:" + ex);
        }
        try {
            config = JSON.parse(configFileText);
            allConfigs.set(configPath, config);
        } catch (ex) {
            return Result.buildErr("配置文件[" + configPath + "]解析失败:" + ex + ", configFileText:" + configFileText);
        }
    }
    return Result.buildSucc(config);
}

declare global {

    /**
     * 获取全局定义的应用数据库连接实例
     *
     * @returns
     */
    function getAppDbHelper(): IDbHelper;
}